//
//  ActiveAIChatExt.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/3/11.
//

import Foundation
import SwiftUI

//检查是否有日记需要回复
class ActiveDiaryReplyExt : BaseViewModel {
    static let instance = ActiveDiaryReplyExt()

    private var mapDelay: [String:Bool] = [:]
    private let modeType = IAiModelType.diaryReply.rawValue
    private let mapQueue = DispatchQueue(label: "mapDelayQueue")
    private let tag = "checkDiaryReply"

    private func getKey(_ id : String?, _ aiRoleId : String?) -> String {
        return "\(id ?? "")_\(aiRoleId ?? "")"
    }
    
    
    func getMapValue(_ key: String) -> Bool {
        return mapQueue.sync {
            self.mapDelay[key] ?? false
        }
    }
    
    func putMapValue(_ key: String,_ bool: Bool) {
        return mapQueue.sync {
            self.mapDelay[key] = bool
        }
    }
    
    func removeMapValue(_ key: String) {
        return mapQueue.sync {
            self.mapDelay.removeValue(forKey: key)
        }
    }

    func checkDiary() {
        request(isLoading: false,timeout: 60 * 60){
            let list = try await BackupsManager.shared.getDelegateDiary()?.queryDiaryLately(userId: userManager.getUserId(), pageNo: 0, pageSize: 20) ?? [DiaryBean]()
            try await DiaryExt.dealPicture(list, true)
            return list
        } suc: { list in
            for diary in list {
                showLog(self.tag, "检查日记信息" + (diary.content ?? ""))
                if (diary.isMultiple()) {
                    //多人回复
                    let listRule : [AiReplyBean] = diary.aiRule?.listAiRole ?? []
                    listRule.forEach {
                        let listContent = $0.content
                        if ((listContent ?? []).isEmpty) {
                            self.doAiReply(diary, $0.roleId ?? "")
                        }
                    }
                } else {
                    //旧版本回复
                    if (diary.aiChat2 == nil && (diary.aiChat ?? "").isEmpty) {
                        self.doAiReply(diary, diary.aiRule?.aiRoleId ?? "")
                    }
                }
                
            }
        } fail: { _ in
            
        }
    }
    
    func doAiReply(_ diaryBean: DiaryBean,
                   _ aiRoleIdFinal: String,
                   _ force: Bool = false,
                   _ backup: Bool = false
                   ) {
        var errorApi = ""
        request(isLoading: false,timeout: 60 * 60){
            var aiRoleId = aiRoleIdFinal
            //            try check(!isExamine()) {
            //                "审核版本，不开启功能"
            //            }
            try check(self.tag, AppStorageManager.shared.toggleAi) {
                "AI 功能已关闭"
            }
            try check(self.tag, AppStorageManager.shared.toggleAiComment) {
                "AI 评论功能已关闭"
            }
            try check(self.tag, AiChatExt.isAiEnabled() || AiCustomUtils.shared.isCustomAi(type: self.modeType)) {
                "AI 功能已用尽,请前往活动领取次数"
            }
            let aiRole = try await BackupsManager.shared.getDelegateConfig()?.getAiRole(roleId: aiRoleId) ?? AiRoleBean()
            if aiRoleId.isEmpty {
                //如果为空，需要赋值
                aiRoleId = aiRole.objectId ?? ""
            }
            let exit  = self.getMapValue(self.getKey(diaryBean.objectId, aiRoleId))
            try check(self.tag, exit == false) {
                "该日记角色已进入延迟阶段"
            }
            self.putMapValue(self.getKey(diaryBean.objectId, aiRoleId),true)
            try await self.doAIImage(diaryBean: diaryBean) //图片理解
            
            let aiModel: Int  = configManager.getConfig().aiChat.getAiModel(aiMode: IAiModelType.diaryReply)
            var replyStr : String = ""
            let listImageDesc = diaryBean.listDiaryPicture?.filter {$0.isImage()}.filter{ ($0.describe ?? "").isEmpty == false}.map { $0.describe ?? ""} ?? [String]()
            
            if backup {
                //启动备用方案
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    let aiModeBean = configManager.getConfig().getAiChatMode2(key: self.modeType)
                    errorApi = "\(aiModeBean.host ?? ""),\(aiModeBean.model ?? "")"
                    let bean = AIDiaryReplayBean(model : aiModeBean.model, content:  diaryBean.content ?? "", botRoleBean: RoleBean.get(aiRole), listImage: listImageDesc)
                    showLog(self.tag, "请求AI：\(String(describing: toJson(bean)))")
                    let result = try await AiNetManager.shared.requestAI(host: aiModeBean.host, token: aiModeBean.token, jsonObject: toJson(bean), modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                    showLog(self.tag, replyStr)
                }
            } else if AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                //自定义
                try await retry(maxRetries: 3, retryDelayMillis: 500) {
                    let host = AiCustomUtils.shared.getCustomHost(type: self.modeType)
                    let token = AiCustomUtils.shared.getCustomToken(type: self.modeType)
                    let model = AiCustomUtils.shared.getCustomModel(type: self.modeType)
                    errorApi = "\(host),\(model)"
                    let bean = AIDiaryReplayBean(model : model, content:  diaryBean.content ?? "", botRoleBean: RoleBean.get(aiRole), listImage: listImageDesc)
                    showLog(self.tag, "请求AI：\(String(describing: toJson(bean)))")
                    let result = try await AiNetManager.shared.requestAI(host: host, token: token, jsonObject: toJson(bean), modeType: AIChatResultBean.self)
                    replyStr = result.getReplyStr()
                    showLog(self.tag, replyStr)
                }
            } else {
                switch aiModel {
                case 1,2:
                    //配置模型
                    try await retry(maxRetries: 1, retryDelayMillis: 500) {
                        let aiModeBean = configManager.getConfig().getAiChatMode(key: self.modeType)
                        errorApi = "\(aiModeBean.host ?? ""),\(aiModeBean.model ?? "")"
                        let bean = AIDiaryReplayBean(model : aiModeBean.model, content:  diaryBean.content ?? "", botRoleBean: RoleBean.get(aiRole), listImage: listImageDesc)
                        showLog(self.tag, "请求AI：\(String(describing: toJson(bean)))")
                        let result = try await AiNetManager.shared.requestAI(host: aiModeBean.host, token: aiModeBean.token, jsonObject: toJson(bean), modeType: AIChatResultBean.self)
                        replyStr = result.getReplyStr()
                        showLog(self.tag, replyStr)
                    }
                default:
                    //minmax 模型
                    try await retry(maxRetries: 3, retryDelayMillis: 500) {
                        let bean = AIDiaryReplayBeanMinmaxBean(content:  diaryBean.content ?? "", botRoleBean: RoleBean.get(aiRole), listImage: listImageDesc)
                        showLog(self.tag, "请求AI：：\(String(describing: toJson(bean)))")
                        let result = try await AiNetManager.shared.requestAIMinMax(jsonObject: toJson(bean), modeType: AIChatResultMinmaxBean.self)
                        replyStr = result.getReplyStr(true)
                    }
                    
                }
            }
            try check(self.tag, !isAiReplyProhibit(replyStr), "AI含有违禁词")
            if diaryBean.isMultiple() {
                //新版本AI回复
                diaryBean.setNewChatAiAll(aiRoleId: aiRole.objectId ?? "", value: replyStr)
            } else {
                //旧版本Ai回复
                diaryBean.setChatAiAll(aiRole: aiRole, value: replyStr)
            }
            //开始保存日记
            try await retry(maxRetries: 10, retryDelayMillis: 500) {
                try await BackupsManager.shared.getDelegateDiary()?.saveDiary(bean: diaryBean)
            }
            return diaryBean
        } suc: { diary in
            if !AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                AiChatExt.deductAiChatCountCommon()
            }
            self.removeMapValue(self.getKey(diaryBean.objectId, aiRoleIdFinal))
            //发送通知
            NotificationCenter.default.post(name: .updateDiary, object: diaryBean)
        } fail: { it in
            self.removeMapValue(self.getKey(diaryBean.objectId, aiRoleIdFinal))
            if ERROR.NET_ERRPR.rawValue == it.code {
                AiChatExt.reportError(
                    type: self.modeType,
                    typeName: "日记回复",
                    message: it.realMessage,
                    errorApi: errorApi)
                
                if let error = configManager.getConfig().getAiError(content: it.realMessage) {
                    showToast(error)
                }
            } else {
                //非自定义使用备用方案
                if !backup && !AiCustomUtils.shared.isCustomAi(type: self.modeType) {
                    showLog(self.tag, "回复使用备用方案")
                    self.doAiReply(diaryBean, aiRoleIdFinal, force, true)
                }
            }
        }
        
    }
    
    private  func doAIImage(diaryBean: DiaryBean) async throws {
        do {
            if AppStorageManager.shared.toggleAiImage == false {
                return
            }
            var count = AppStorageManager.shared.aiImageCount
            if (count == 0) {
                count = 1
            }
            //只处理图片
            var listImage = diaryBean.listDiaryPicture?.filter {$0.isImage()}.prefix(count).filter{ ($0.describe ?? "").isEmpty == true }.map {
                let bean = ImageAiBean()
                bean.path = $0.getAiPath()
                return bean
            } ?? [ImageAiBean]()
            if listImage.isEmpty == true {
                return
            }
            showLog(self.tag, "识别图片")
            listImage = try await ImageAiExt.instance.doAIImage(list: listImage, content: diaryBean.content ?? "")
            for imageAi in listImage {
                for picture in diaryBean.listDiaryPicture ?? [] {
                    if (imageAi.path == picture.getAiPath()) {
                        picture.describe = imageAi.describe
                        //保存图片
                        try await BackupsManager.shared.getDelegateDiary()?.saveCloudPicture(bean: picture)
                    }
                }
            }
        } catch let error {
            showLog(self.tag, "识别失败:\(error.localizedDescription)")
        }
    }
}

